/*
* Copyright (C) 2012-2014 qar
* License: http://www.gnu.org/licenses/gpl.html GPL version 2
*/

#include "crypto/authenticator.h"

#include "crypto/auth/signer.h"
#include "crypto/auth/signernull.h"

Authenticator::Authenticator(Authenticator::AuthenticationAlgorithm algorithm, QString keyFile)
    : algorithm(algorithm),
      keyFile(keyFile),
      signer(NULL)
{
    setAlgorithm(algorithm, keyFile);
}

Authenticator::~Authenticator()
{
    delete signer;
    signer = NULL;
}

void Authenticator::setAlgorithm(Authenticator::AuthenticationAlgorithm algorithm, QString keyFile)
{
    delete signer;
    signer = NULL;

    this->algorithm = algorithm;
    this->keyFile = keyFile;

    if (algorithm == Authenticator::NoAuthentication) {
        signer = new SignerNull();
    }
}

Authenticator::AuthenticationAlgorithm Authenticator::getAlgorithm() const
{
    return algorithm;
}

QString Authenticator::getAlgorithmName() const
{
    return signer->getAlgorithmName();
}

qint64 Authenticator::hashSize() const
{
    return signer->hashSize();
}

void Authenticator::signSegment(const QByteArray &segment, QByteArray &signedSegment)
{
    signer->signSegment(segment, signedSegment);
}

bool Authenticator::checkAndExtractSegment(const QByteArray &signedSegment, QByteArray &segment)
{
    return signer->checkAndExtractSegment(signedSegment, segment);
}

bool Authenticator::toStream(QDataStream &s)
{
    qint32 authenticationAlgorithmEncoded = algorithm;
    s << authenticationAlgorithmEncoded;

    if (!signer->toStream(s))
        return false;

    return s.status() == QDataStream::Ok;
}

bool Authenticator::fromStream(QDataStream &s)
{
    qint32 authenticationAlgorithmEncoded;
    s >> authenticationAlgorithmEncoded;
    if (s.status() != QDataStream::Ok)
        return false;

    if (authenticationAlgorithmEncoded == Authenticator::NoAuthentication) {
        setAlgorithm(Authenticator::NoAuthentication, keyFile);
        if (!signer->fromStream(s))
            return false;
    } else {
        return false;
    }

    return true;
}
